const path = require("path");
const redis = require('redis');
const sync = require('pomelo-sync-plugin');

const pomelo = require('pomelo');
const app = pomelo.createApp();
const dispatcher = require('./app/util/dispatcher');
const AreaService = require('./app/service/areaService');
const LoginService = require('./app/service/loginService');
const boxFilter = require('./app/servers/box/filter/boxFilter');
const upgradeFilter = require('./app/servers/upgrade/filter/upgradeFilter');
const exchangeFilter = require('./app/servers/exchange/filter/exchangeFilter');
const exchangeEssenceFilter = require('./app/servers/exchangeEssence/filter/exchangeFilter');
const loginFilter = require('./app/servers/login/filter/loginFilter');
const luckDrawFilter = require('./app/servers/luckDraw/filter/luckDrawFilter');
const welfareFilter = require('./app/servers/welfare/filter/welfareFilter');
const boxConsts = require('./app/servers/box/lib/consts');
const Consts = require('./app/util/consts');

const {incomeSpeedUpEnd} = require('./app/servers/upgrade/lib/action');

app.set('name', 'oil');

// 设置路径
app.set('utilsPath', path.join(path.join(app.getBase(), 'app'), 'util'));
app.set("configPath", path.join(app.getBase(), "config"));

// 设置redis缓存对象
app.loadConfig('redisConfig', path.join(app.get('configPath'), 'redis'));
app.set('redis', require(path.join(app.get('utilsPath'), 'redis'))(app.get('redisConfig')));

// 获取MySQL配置
app.loadConfig("mysql", app.getBase() + "/shared/config/mysql.json");
app.set("mysqlClient", require("./shared/mysql.js").init(app));

// app configuration
app.configure('production|development', function () {
    // 开启系统监控
    //app.enable('systemMonitor');
    // 配置自定义监控，运行自定义统计脚本收集服务器运行数据，为服务器注册自定义监控模块
    //if(typeof app.registerAdmin === 'function'){
    // 将监控在线用户模块注册给所有服务器
    //  app.registerAdmin('online', require('./app/modules/online'), {app: app});
    //}
    app.route('area', areaRoute);
    app.route('box', boxRoute);
    app.route('exchange', exchangeRoute);
    app.route('upgrade', upgradeRoute);
    app.route('login', loginRoute);
    app.route('mission', missionRoute);
    app.route('video', videoRoute);
    app.route('player', playerRoute);
    app.route('luckDraw', luckDrawRoute);
    app.route('exchangeEssence', exchangeEssenceRoute);
    app.route('welfare', welfareRoute);
    //将userRemote挂载到app上方便使用
    app.userRemote = userRemoteMount;
});
app.configure('production|development', 'area|connector|master|login|mission', function () {
    // 将内存中数据同步到数据库的插件
    var mongoose = require('./app/dao/mongo/mongo');
    app.use(sync, {sync: {path: __dirname + '/app/dao/mapping', dbclient: mongoose}});
});
app.configure('production|development', 'gate', function () {
    app.set('connectorConfig', {connector: pomelo.connectors.hybridconnector});
});
app.configure('production|development', 'connector', function () {
    app.set('connectorConfig',
        {
            connector: pomelo.connectors.hybridconnector,
            heartbeat: 10,
            useDict: true,
            useProtobuf: true
        });
    // 每隔5秒打印当前在线人数
    setInterval(() => {
        const stats = app.components.__connection__.getStatisticsInfo();
        // console.log("connection statistics info:", stats);
    }, 5000);
});
app.configure('production|development', 'area', function () {
    app.areaService = new AreaService();
});
app.configure('production|development', 'login', function () {
    app.filter(loginFilter());
    app.loginService = new LoginService();
});


app.configure('production|development', 'box|upgrade', function () {
    app.filter(boxFilter());

    const sub = redis.createClient(app.get('redisConfig'));
    const expired_subKey = '__keyevent@' + app.get('redis').options.db + '__:expired';
    //监听超时事件
    sub.subscribe(expired_subKey, function () {
        sub.on('message', function (chan, key) {
            if (key.indexOf(boxConsts.BOX_OVER_TIME) === 0) { //宝箱到期事件
                //获取本倒计时结束事件的uid
                let uid = key.slice(boxConsts.BOX_OVER_TIME.length, key.indexOf('@'))
                //验证是否由此box服务器处理
                let boxServers = app.getServersByType('box');
                let res = dispatcher.dispatch(uid, boxServers).id;
                if (app.serverId != res) return;
                //宝箱倒计时结束事件处理
                boxOverTimeEmit(uid, key);
                return;
            } else if (key.indexOf(Consts.RedisPrefix.DOUBLE_REWARD) === 0) { //双倍奖励到期事件
                let uid = key.slice(Consts.RedisPrefix.DOUBLE_REWARD.length, key.indexOf('@'))
                //验证是否由此box服务器处理
                let upgradeServers = app.getServersByType('upgrade');
                let connectorServers = app.getServersByType('connector');
                let loginServers = app.getServersByType('login');
                let upgrade_id = dispatcher.dispatch(uid, upgradeServers).id;
                let frontend_id = dispatcher.dispatch(uid, connectorServers).id;
                let login_id = dispatcher.dispatch(uid, loginServers).id;
                if (app.serverId != upgrade_id) return;
                doubleRewardFinish(uid, key, upgrade_id, frontend_id, login_id);
                return;
            }
        });
    });
});


app.configure('production|development', function() {
	app.enable('systemMonitor');
	var onlineUser = require('./app/onlineUser/onlineUser');
	if(typeof app.registerAdmin === 'function'){
		//app.registerAdmin(sceneInfo, {app: app});
		app.registerAdmin(onlineUser, {app: app});
	}
});

app.configure('production|development', 'upgrade', function () {
    app.filter(upgradeFilter());
});
app.configure('production|development', 'signIn', function () {
    app.filter(signInFilter());
});
app.configure('production|development', 'exchange', function () {
    app.filter(exchangeFilter());
});
app.configure('production|development', 'exchangeEssence', function () {
    app.filter(exchangeEssenceFilter());
});
app.configure('production|development', 'luckDraw', function () {
    app.filter(luckDrawFilter());
    //采集加速时间结束事件
    // incomeSpeedUpEnd.call({app});
});
app.configure('production|development', 'welfare', function () {
    app.filter(welfareFilter());
});

app.start();

process.on('uncaughtException', function (err) {
    console.error(' Caught exception: ' + err.stack);
});

function areaRoute(session, msg, app, cb) {
    var areaServers = app.getServersByType('area');
    if (!areaServers || areaServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), areaServers);
    cb(null, res.id);
};

function boxRoute(session, msg, app, cb) {
    var boxServers = app.getServersByType('box');
    if (!boxServers || boxServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), boxServers);
    cb(null, res.id);
}

function exchangeRoute(session, msg, app, cb) {
    var exchangeServers = app.getServersByType('exchange');
    if (!exchangeServers || exchangeServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), exchangeServers);
    cb(null, res.id);
}

function upgradeRoute(session, msg, app, cb) {
    var upgradeServers = app.getServersByType('upgrade');
    if (!upgradeServers || upgradeServers.length === 0) {
        cb(new Error('can not find upgrade servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), upgradeServers);
    cb(null, res.id);
}

function loginRoute(session, msg, app, cb) {
    var loginServers = app.getServersByType('login');
    if (!loginServers || loginServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    if (session) {
        if (msg.namespace === 'user' && msg.serverType === 'login' && msg.service === 'loginRemote' && msg.method === 'addApprentice') {
            cb(null, dispatcher.dispatch(msg.args[0], loginServers).id);
        } else if (msg.namespace === 'user' && msg.serverType === 'login' && msg.service === 'loginRemote' && msg.method === 'addDisciple') {
            cb(null, dispatcher.dispatch(msg.args[0], loginServers).id);
        } else {
            cb(null, dispatcher.dispatch(session.get('uid'), loginServers).id);
        }
    } else {
        if (msg && msg.args[0].type === 'getAllUser') {
            for (let i = 0; i < loginServers.length; i++) {
                cb(null, loginServers[i].id);
            }
        } else { //if(msg && msg.args[1].type === 'setUser')
            cb(null, dispatcher.dispatch(msg.args[0].uid, loginServers).id);
        }
    }
};

function missionRoute(session, msg, app, cb) {
    var missionServers = app.getServersByType('mission');
    if (!missionServers || missionServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), missionServers);
    cb(null, res.id);
}

function videoRoute(session, msg, app, cb) {
    var videoServers = app.getServersByType('video');
    if (!videoServers || videoServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), videoServers);
    cb(null, res.id);
}

function playerRoute(session, msg, app, cb) {
    var userServers = app.getServersByType('player');
    if (!userServers || userServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), userServers);
    cb(null, res.id);
}

function luckDrawRoute(session, msg, app, cb) {
    var luckDrawServers = app.getServersByType('luckDraw');
    if (!luckDrawServers || luckDrawServers.length === 0) {
        cb(new Error('can not find chat servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), luckDrawServers);
    cb(null, res.id);
}

function exchangeEssenceRoute(session, msg, app, cb) {
    var exchangeEssenceServers = app.getServersByType('exchangeEssence');
    if (!exchangeEssenceServers || exchangeEssenceServers.length === 0) {
        cb(new Error('can not find exchangeEssenceServers servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), exchangeEssenceServers);
    cb(null, res.id);
}

function welfareRoute(session, msg, app, cb) {
    var welfareServers = app.getServersByType('welfare');
    if (!welfareServers || welfareServers.length === 0) {
        cb(new Error('can not find welfareServers servers.'));
        return;
    }
    var res = dispatcher.dispatch(session.get('uid'), welfareServers);
    cb(null, res.id);
}

//宝箱超时事件发送
function boxOverTimeEmit(uid, key) {
    let boxServers = app.getServersByType('box');
    let boxServersId = dispatcher.dispatch(uid, boxServers).id;
    app.rpcInvoke(boxServersId, {
        namespace: 'user',
        serverType: 'box',
        service: 'boxRemote',
        method: 'endCountDown',
        args: [key]
    }, function () {
    });
}

//双倍奖励结束事件
function doubleRewardFinish(uid, key, serverId, frontendId, loginId) {
    app.rpcInvoke(serverId, {
        namespace: 'user',
        serverType: 'box',
        service: 'upgradeRemote',
        method: 'doubleRewardFinish',
        args: [
            uid,
            frontendId,
            loginId,
        ]
    }, function () {
    });
}

//将userRemote挂载到app上方便使用
function userRemoteMount(uid, method, args) {
    return new Promise((resolve, reject) => {
        let loginServers = app.getServersByType('login');
        let loginServerId = dispatcher.dispatch(uid, loginServers).id;
        app.rpcInvoke(loginServerId, {
            namespace: 'user',
            serverType: 'login',
            service: 'userRemote',
            method: method,
            args: args
        }, function (err, data) {
            if (err) return reject(err);
            resolve(data);
        });
    });
}
